# -*- coding: utf-8 -*-
"""
****************************
@Time    : 2021/4/28 8:55
@Author  : Candy
@File    : auth.py
****************************
"""
import base64
import datetime
import hashlib
import json
import random
import time

from urllib import parse

from configer import JWT_NOISE

RANDOM = r"""abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"""


class MiniJWT:
    """加入重刷机制 用户携带分发的短效token进行每次的接口认证 长期token由客户端定时发送刷新"""

    def __init__(self):
        self.__noise = JWT_NOISE
        self.__header = {
            "alg": "SHA256",
            "typ": "MiniJWT"
        }
        self.shuffle_count = 0

    def build(self, uid, level, ip, client):
        # 新增打乱次数随机
        self.shuffle_count = datetime.datetime.now().day % 5 + 2
        header = self.__m_encode(self.__header)
        payload = self.__m_encode({"uid": uid, "ip": ip, "client": client, "exp": time.time() + 15 * 60, "level": level})
        signore = self.__m_sha256(header + payload)
        payload = self.shuffle(''.join([i + RANDOM[random.randint(0, 63)] for i in payload]), self.shuffle_count)
        return parse.quote(header + '_' + payload + '_' + signore + '_' + str(self.shuffle_count))

    def shuffle(self, text, count):
        while count:
            old = ''.join([v for i, v in enumerate(text) if i & 1])  # 把偶数位提前（index为奇数）
            no_old = ''.join([v for i, v in enumerate(text) if not i & 1])
            return self.shuffle(old + no_old, count-1)
        return text

    def un_shuffle(self, text, count):
        while count:
            old = text[:len(text)//2]  # 前置向后
            no_old = text[len(text)//2:]  # 后置向前
            text = ''.join([i[0]+i[1] for i in zip(no_old, old)])
            return self.un_shuffle(text, count-1)
        return text

    def check(self, val, now_ip, now_client):
        # print(val, now_ip, now_client)
        try:
            val = parse.unquote(val)
            header, payload, signore, shuffle_count = val.split('_')
            payload = ''.join([v for i, v in enumerate(self.un_shuffle(payload, int(shuffle_count))) if not i & 1])
        except Exception:
            return False, 0, 0, 0
        if self.__m_sha256(header+payload) != signore:
            return False, 0, 0, 0
        info = self.__m_decode(payload)
        if info['ip'] != now_ip or info['client'] != now_client:
            return False, 0, 0, 0
        if info['exp'] < time.time():
            return False, 0, 0, 0
        return True, info['uid'], info['exp'], info["level"]

    def get_aid(self, val):
        try:
            payload = val.split(".")[1]
            payload = ''.join([v for i, v in enumerate(self.un_shuffle(payload, self.shuffle_count)) if not i & 1])
            return self.__m_decode(payload).get('uid', 0)
        except Exception:
            return 0

    def __m_encode(self, val):
        return base64.b64encode(json.dumps(val).encode('utf-8')).decode('utf-8')

    def __m_decode(self, val):
        return json.loads(base64.b64decode(val))

    def __m_sha256(self, val):
        h = hashlib.sha256()
        h.update((val.encode('utf-8') + self.__noise.encode('utf-8')))
        return h.hexdigest()

    @staticmethod
    def get_limit_time(time_):
        """是否刷新token"""
        return False if int((time.time() - time_) < -(5 * 60)) else True

    def refresh(self, uid, level, now_ip, now_client):
        """刷新token 替换即将到期的token"""
        return self.build(uid, level, now_ip, now_client)


if __name__ == '__main__':
    # m = MiniJWT()
    # a = m.build(0, "1", "2")
    # print(a)
    # status, _ = m.check(a, "1", "2")
    # if status:
    #     print(m.get_aid(a))
    # else:
    #     print('err')
    m1 = MiniJWT()
    a = 'eyJhbGciOiAiU0hBMjU2IiwgInR5cCI6ICJNaW5pSldUIn0%3D_ksUvjdwggiX4otzz%3DgOWUwhpXwAhBA9Uc%3DAJiwwMNTSCCyimzDQejSdYBfOOLIONcLOfsBIIvUKDxiw0zop1xjjzDwIrkAQ4Y4NJQEmBJzGeuJiTSjyEXDDifTZwawSONNbNIYNIYrHkiLKeixvpzpm56eAgIfJecQ4EdU8FMIehstpQLQWyGFz22jCmQiiWxRFaMbILaUNbNRfZBDqw1us70jgxlpqrXjZCMJMlAlVQAZbzQcheUayTmj22TiXhXegdgVOeMeLSRNOZRgbOVrenCxvwiguisVocVapfsp41EVUgAJjfkCbvpzBCkD22zHCaeCdGLtFhOIIVaMeIGolwkZcWzxgUlp2lsujhJJUhLTEo5xxQJQxCWrSFthJjjEGGjCzdXUiTntttIIIcILIMECvtkAFpdg0zwswszNezbbarXeo5dFw4IIjkVlbCfntjW3EUSiTBnmgPQiGkIZbITNNOcVRWCFEcYwpkpU5zxkrfRWYgErlx5Qh84gdjcLatbOpm2Wj0SyjQaiLleicEIYaNSZNL_68d1433886a570f224512a97283fb5abf9006f2c51fad415d3a2c4a6cbcb7e0b'
    print(m1.check(a, "118.113.3.154", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36"))
